
/*
 * Copyright 2002-2017 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 *版权所有2002-2017原作者。
 *
 *根据Apache许可证2.0版（“许可证”）获得许可；
 *除非符合许可证，否则不得使用此文件。
 *您可以在以下地址获取许可证副本：
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 *除非适用法律要求或书面同意，软件
 *根据许可证分发的内容是按“原样”分发的，
 *无任何明示或暗示的保证或条件。
 *有关管理权限和
 *许可证下的限制。
 */

package org.springframework.beans.factory.xml;

import org.w3c.dom.Element;

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.lang.Nullable;

/**
 * Base class for those {@link BeanDefinitionParser} implementations that
 * need to parse and define just a <i>single</i> {@code BeanDefinition}.
 *
 * <p>Extend this parser class when you want to create a single bean definition
 * from an arbitrarily complex XML element. You may wish to consider extending
 * the {@link AbstractSimpleBeanDefinitionParser} when you want to create a
 * single bean definition from a relatively simple custom XML element.
 *
 * <p>The resulting {@code BeanDefinition} will be automatically registered
 * with the {@link org.springframework.beans.factory.support.BeanDefinitionRegistry}.
 * Your job simply is to {@link #doParse parse} the custom XML {@link Element}
 * into a single {@code BeanDefinition}.
 *
 * @author Rob Harrop
 * @author Juergen Hoeller
 * @author Rick Evans
 * @since 2.0
 * @see #getBeanClass
 * @see #getBeanClassName
 * @see #doParse
 */
/**
 *｛@link BeanDefinitionParser｝实现的基类
 *只需要解析和定义一个＜i＞＜/i＞｛@code BeanDefinition｝。
 *
 *＜p＞当您想要创建单个bean定义时，扩展这个解析器类
 *来自任意复杂的XML元素。您可能希望考虑延长
 *｛@link AbstractSimpleBeanDefinitionParser｝
 *一个相对简单的自定义XML元素的单个bean定义。
 *
 *＜p＞生成的｛@code BeanDefinition｝将自动注册
 *使用{@link.org.springframework.beans.factory.support.BeanDefinitionRegistry}。
 *您的工作只是｛@link#doParse解析｝自定义XML｛@link元素｝
 *转换为单个｛@code BeanDefinition｝。
 *
 *@作者Rob Harrop
 *@作者Juergen Hoeller
 *@作者Rick Evans
 *@自2.0起
 *@参见#getBeanClass
 *@参见#getBeanClassName
 *@参见#doParse
 */
public abstract class AbstractSingleBeanDefinitionParser extends AbstractBeanDefinitionParser {

	/**
	 * Creates a {@link BeanDefinitionBuilder} instance for the
	 * {@link #getBeanClass bean Class} and passes it to the
	 * {@link #doParse} strategy method.
	 * @param element the element that is to be parsed into a single BeanDefinition
	 * @param parserContext the object encapsulating the current state of the parsing process
	 * @return the BeanDefinition resulting from the parsing of the supplied {@link Element}
	 * @throws IllegalStateException if the bean {@link Class} returned from
	 * {@link #getBeanClass(org.w3c.dom.Element)} is {@code null}
	 * @see #doParse
	 */
	/**
	 *为
	 *｛@link#getBeanClassbean类｝并将其传递给
	 *｛@link#doParse｝策略方法。
	 *@param元素要解析为单个BeanDefinition的元素
	 *@param parserContext封装解析过程当前状态的对象
	 *@return解析所提供的｛@link元素｝所产生的BeanDefinition
	 *如果从
	 *｛@link#getBeanClass（org.w3c.dom.Element）｝是｛@code null｝
	 *@参见#doParse
	 */
	@Override
	protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
		BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
		String parentName = getParentName(element);
		if (parentName != null) {
			builder.getRawBeanDefinition().setParentName(parentName);
		}
		Class<?> beanClass = getBeanClass(element);
		if (beanClass != null) {
			builder.getRawBeanDefinition().setBeanClass(beanClass);
		}
		else {
			String beanClassName = getBeanClassName(element);
			if (beanClassName != null) {
				builder.getRawBeanDefinition().setBeanClassName(beanClassName);
			}
		}
		builder.getRawBeanDefinition().setSource(parserContext.extractSource(element));
		BeanDefinition containingBd = parserContext.getContainingBeanDefinition();
		if (containingBd != null) {
			// Inner bean definition must receive same scope as containing bean.
			// 内部bean定义必须接收与包含bean相同的作用域。
			builder.setScope(containingBd.getScope());
		}
		if (parserContext.isDefaultLazyInit()) {
			// Default-lazy-init applies to custom bean definitions as well.
			// 默认的惰性初始化也适用于自定义bean定义。
			builder.setLazyInit(true);
		}
		doParse(element, parserContext, builder);
		return builder.getBeanDefinition();
	}

	/**
	 * Determine the name for the parent of the currently parsed bean,
	 * in case of the current bean being defined as a child bean.
	 * <p>The default implementation returns {@code null},
	 * indicating a root bean definition.
	 * @param element the {@code Element} that is being parsed
	 * @return the name of the parent bean for the currently parsed bean,
	 * or {@code null} if none
	 */
	/**
	 *确定当前解析的bean的父级的名称，
	 *在当前bean被定义为子bean的情况下。
	 *＜p＞默认实现返回｛@code null｝，
	 *指示根bean定义。
	 *@param元素正在解析的｛@code元素｝
	 *@return当前解析的bean的父bean的名称，
	 *或｛@code null｝（如果没有）
	 */
	@Nullable
	protected String getParentName(Element element) {
		return null;
	}

	/**
	 * Determine the bean class corresponding to the supplied {@link Element}.
	 * <p>Note that, for application classes, it is generally preferable to
	 * override {@link #getBeanClassName} instead, in order to avoid a direct
	 * dependence on the bean implementation class. The BeanDefinitionParser
	 * and its NamespaceHandler can be used within an IDE plugin then, even
	 * if the application classes are not available on the plugin's classpath.
	 * @param element the {@code Element} that is being parsed
	 * @return the {@link Class} of the bean that is being defined via parsing
	 * the supplied {@code Element}, or {@code null} if none
	 * @see #getBeanClassName
	 */
	/**
	 *确定与提供的｛@link Element｝相对应的bean类。
	 *＜p＞注意，对于应用程序类，通常最好
	 *替代｛@link#getBeanClassName｝，以避免直接
	 *依赖于bean实现类。BeanDefinitionParser
	 *并且它的NamespaceHandler可以在IDE插件中使用，甚至
	 *如果应用程序类在插件的类路径上不可用。
	 *@param元素正在解析的｛@code元素｝
	 *@return通过解析定义的bean的｛@link Class｝
	 *提供的｛@code Element｝，如果没有，则返回｛@ccode null｝
	 *@参见#getBeanClassName
	 */
	@Nullable
	protected Class<?> getBeanClass(Element element) {
		return null;
	}

	/**
	 * Determine the bean class name corresponding to the supplied {@link Element}.
	 * @param element the {@code Element} that is being parsed
	 * @return the class name of the bean that is being defined via parsing
	 * the supplied {@code Element}, or {@code null} if none
	 * @see #getBeanClass
	 */
	/**
	 *确定与提供的｛@link Element｝相对应的bean类名。
	 *@param元素正在解析的｛@code元素｝
	 *@return通过解析定义的bean的类名
	 *提供的｛@code Element｝，如果没有，则返回｛@ccode null｝
	 *@参见#getBeanClass
	 */
	@Nullable
	protected String getBeanClassName(Element element) {
		return null;
	}

	/**
	 * Parse the supplied {@link Element} and populate the supplied
	 * {@link BeanDefinitionBuilder} as required.
	 * <p>The default implementation delegates to the {@code doParse}
	 * version without ParserContext argument.
	 * @param element the XML element being parsed
	 * @param parserContext the object encapsulating the current state of the parsing process
	 * @param builder used to define the {@code BeanDefinition}
	 * @see #doParse(Element, BeanDefinitionBuilder)
	 */
	/**
	 *分析提供的｛@link元素｝并填充提供的
	 *｛@link BeanDefinitionBuilder｝。
	 *＜p＞默认实现委托给｛@code doParse｝
	 *没有ParserContext参数的版本。
	 *@param元素正在解析的XML元素
	 *@param parserContext封装解析过程当前状态的对象
	 *@param生成器用于定义｛@code BeanDefinition｝
	 *@see#doParse（元素，BeanDefinitionBuilder）
	 */
	protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
		doParse(element, builder);
	}

	/**
	 * Parse the supplied {@link Element} and populate the supplied
	 * {@link BeanDefinitionBuilder} as required.
	 * <p>The default implementation does nothing.
	 * @param element the XML element being parsed
	 * @param builder used to define the {@code BeanDefinition}
	 */
	/**
	 *分析提供的｛@link元素｝并填充提供的
	 *｛@link BeanDefinitionBuilder｝。
	 *＜p＞默认实现不执行任何操作。
	 *@param元素正在解析的XML元素
	 *@param生成器用于定义｛@code BeanDefinition｝
	 */
	protected void doParse(Element element, BeanDefinitionBuilder builder) {
	}

}
